use std::fmt::{self, Display};
use super::ToTokens;

#[derive(Debug, Clone)]
pub struct Tokens(String);

impl Tokens {
    pub fn new() -> Self {
        Tokens(String::new())
    }

    pub fn append(&mut self, token: &str) {
        self.0.push_str(token);
        self.0.push(' ');
    }

    pub fn append_all<T, I>(&mut self, iter: I)
        where T: ToTokens,
              I: IntoIterator<Item = T>
    {
        for token in iter {
            token.to_tokens(self);
        }
    }

    pub fn append_separated<T, I>(&mut self, iter: I, sep: &str)
        where T: ToTokens,
              I: IntoIterator<Item = T>
    {
        for (i, token) in iter.into_iter().enumerate() {
            if i > 0 {
                self.append(sep);
            }
            token.to_tokens(self);
        }
    }

    pub fn append_terminated<T, I>(&mut self, iter: I, term: &str)
        where T: ToTokens,
              I: IntoIterator<Item = T>
    {
        for token in iter {
            token.to_tokens(self);
            self.append(term);
        }
    }
}

impl Display for Tokens {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl Default for Tokens {
    fn default() -> Self {
        Tokens::new()
    }
}
